package Objets;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.MessageElement;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.pipe.*;
import net.jxta.protocol.PipeAdvertisement;

/**
 *
 * @author Nono
 */
public class SuperPair extends Pair implements OutputPipeListener, PipeMsgListener {

    /*
     * Pipe commun à tous les SuperPair de chaque groupe
     */
    private PipeService superPipe;
    private PipeAdvertisement superPipeAdv;
    private InputPipe superPipeIn = null;
    private Groupe monGroupe;
    private ArrayList<String> indexFile;
    private boolean hasResponse = false;

    public SuperPair(String nom) {
        super(nom);
        indexFile = new ArrayList<String>();
    }

    @Override
    public void run() {
        try {
            // the following creates the inputpipe, and registers "this"
            // as the PipeMsgListener, when a message arrives pipeMsgEvent is called
            superPipeIn = superPipe.createInputPipe(superPipeAdv, this);
        } catch (Exception e) {
            System.out.println("catched super !!");
            return;
        }
        if (superPipeIn == null) {
            System.out.println(" cannot open Super InputPipe");
            System.exit(-1);
        }

        super.run();
    }

    private String[] preTraitementMsg(Message msg) {
        String delimiter = " ";
        String msgContent = "";
        String[] tmp;
        Message.ElementIterator it = msg.getMessageElements(); 
        while (it.hasNext()) {
            MessageElement el = (MessageElement) it.next();
            msgContent = el.getElementName();
        }
        tmp = msgContent.split(delimiter);
        if(!tmp[0].equals("repgroupe") && !tmp[0].equals(nom)){
            System.out.println("-------------Group Message Receive---------------------");
            System.out.println("Message : " + msgContent);
            System.out.println("-------------------End of Message---------------------");
        }
        return tmp;
    }

    @Override
    public void pipeMsgEvent(PipeMsgEvent event) {
        Message msg = null;
        String[] tmp;
        String peerName = null, action = null, cible = null;
        try {
            // grab the message from the event
            msg = event.getMessage();
            if (msg == null) {
                return;
            }

            if (event.getPipeID() == this.groupePipeAdv.getPipeID()) { //pipe de groupe
                tmp = preTraitementMsg(msg);
                if (tmp.length == 3) {
                    peerName = tmp[0];
                    action = tmp[1];
                    cible = tmp[2];
                    if (action.equals("ajouter")) {
                        if (!this.monGroupe.getBlacklist().contains(peerName)) {
                            this.putFile(cible);
                            System.out.println("Le fichier "+cible+" a été ajouté à l'index");
                        }
                    } else if (action.equals("chercher")) {
                        if (!this.monGroupe.getBlacklist().contains(peerName)) {
                            if (this.searchFile(cible)) {
                                respSearch(true);
                            } else {
                                rechercheFichierSP(cible);
                                Thread.sleep(5000);
                                respSearch(hasResponse);
                            }
                        }
                    } else if (action.equals("chercherSP")) {
                        if (!this.monGroupe.getBlacklist().contains(peerName) && !(this.getNom().equals(peerName))) {
                            if (this.searchFile(cible)) {
                                respSearch(true);
                            } else {
                                rechercheFichierSP(cible);
                                Thread.sleep(5000);
                                respSearch(hasResponse);
                            }
                        }
                    } else if (action.equals("bannir")) {
                        if (this.getNom().equals(peerName) && !this.monGroupe.getBlacklist().contains(cible)) {
                            this.monGroupe.getBlacklist().add(cible);
                            System.out.println("L'utilisateur "+cible+" a été banni");
                        } else if (!this.monGroupe.getBlacklist().contains(peerName) && !this.monGroupe.getBlacklist().contains(cible)) {
                            System.out.println("Voulez vous bannir " + cible + " ? Pour bannir cette personne taper : bannir "+cible);
                        }
                    } else if (action.equals("debannir") && this.getNom().equals(peerName)) {
                        this.monGroupe.getBlacklist().remove(cible);
                        System.out.println("L'utilisateur "+cible+" a été débanni");
                    }
                }
            } else if (event.getPipeID() == this.superPipeAdv.getPipeID()) //c'est le pipe_entree
            {
                tmp = preTraitementMsg(msg);
                if (tmp.length == 3) {
                    peerName = tmp[0];
                    action = tmp[1];
                    cible = tmp[2];
                    if (action.equals("groupe")) {
                        if (cible.equals(this.monGroupe.getNom())) {
                            respAuthorization(this.monGroupe.getBlacklist().contains(peerName));
                        }
                    } else if (action.equals("repchercher")) {
                        hasResponse = true;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

    private void respAuthorization(boolean bool) {
        try {
            String infosAdv = this.groupePipeAdv.getPipeID() + " " + groupePipeAdv.getName() + " " + groupePipeAdv.getType();
            if (bool) {
                this.setMessageSend("repgroupe denied");
            } else {
                this.setMessageSend("repgroupe authorized " + infosAdv);
            }
            superPipe.createOutputPipe(superPipeAdv, this);
        } catch (IOException ex) {
            Logger.getLogger(SuperPair.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void respSearch(boolean bool) {
        try {
            if (bool) {
                this.setMessageSend("repchercher trouve");
            } else {
                this.setMessageSend("repchercher nonTrouve ");
            }
            groupePipe.createOutputPipe(groupePipeAdv, this);
        } catch (IOException ex) {
            Logger.getLogger(SuperPair.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void rechercheFichierSP(String cible) {
        try {
            this.setMessageSend(this.getNom() + " chercherSP " + cible);
            superPipe.createOutputPipe(superPipeAdv, this);
        } catch (IOException ex) {
            Logger.getLogger(SuperPair.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void outputPipeEvent(OutputPipeEvent event) {

        OutputPipe op = event.getOutputPipe();
        Message msg = null;

        try {
            msg = new Message();
            Date date = new Date(System.currentTimeMillis());
            StringMessageElement sme = new StringMessageElement(this.getMessageSend(), date.toString(), null);;
            msg.addMessageElement(null, sme);
            op.send(msg);
        } catch (IOException e) {
            System.out.println("failed to send message");
            e.printStackTrace();
            System.exit(-1);
        }
        op.close();
    }
    
    public void putFile(String s) {
        indexFile.add(s);
    }

    public boolean searchFile(String s) {
        return indexFile.contains(s);
    }

    public PipeService getSuperPipe() {
        return superPipe;
    }

    public void setSuperPipe(PipeService superPipe) {
        this.superPipe = superPipe;
    }

    public PipeAdvertisement getSuperPipeAdv() {
        return superPipeAdv;
    }

    public void setSuperPipeAdv(PipeAdvertisement superPipeAdv) {
        this.superPipeAdv = superPipeAdv;
    }

    public InputPipe getSuperPipeIn() {
        return superPipeIn;
    }

    public void setSuperPipeIn(InputPipe superPipeIn) {
        this.superPipeIn = superPipeIn;
    }

    public Groupe getMonGroupe() {
        return monGroupe;
    }

    public void setMonGroupe(Groupe monGroupe) {
        this.monGroupe = monGroupe;
    }

}
